package view;

import dao.DataManager;
import model.*;
import util.CinemaUtil;
import util.InputUtil;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ManagerView {
    private final DataManager dataManager;
    private final User currentUser;

    public ManagerView(User currentUser) {
        this.dataManager = DataManager.getInstance();
        this.currentUser = currentUser;
    }

    public void showMenu() {
        while (true) {
            System.out.println("\n===== 经理菜单 =====");
            System.out.println("1. 密码管理");
            System.out.println("2. 影片管理");
            System.out.println("3. 排片管理");
            System.out.println("4. 查看销售数据");
            System.out.println("5. 退出登录");
            System.out.print("请选择操作: ");

            int choice = InputUtil.readIntRange("", 1, 5);

            switch (choice) {
                case 1:
                    showPasswordMenu();
                    break;
                case 2:
                    showMovieMenu();
                    break;
                case 3:
                    showScreeningMenu();
                    break;
                case 4:
                    showSalesMenu();
                    break;
                case 5:
                    System.out.println("已退出经理账户");
                    return;
            }
        }
    }

    private void showPasswordMenu() {
        while (true) {
            System.out.println("\n===== 密码管理 =====");
            System.out.println("1. 修改自身密码");
            System.out.println("2. 重置前台用户密码");
            System.out.println("3. 返回上级菜单");
            System.out.print("请选择操作: ");

            int choice = InputUtil.readIntRange("", 1, 3);

            switch (choice) {
                case 1:
                    changeOwnPassword();
                    break;
                case 2:
                    resetFrontDeskPassword();
                    break;
                case 3:
                    return;
            }
        }
    }

    private void changeOwnPassword() {
        String oldPassword = InputUtil.readNonEmptyString("请输入当前密码: ");
        if (!oldPassword.equals(currentUser.getPassword())) {
            System.out.println("当前密码不正确，无法修改密码！");
            return;
        }

        String newPassword = InputUtil.readNonEmptyString("请输入新密码: ");
        String confirmPassword = InputUtil.readNonEmptyString("请再次输入新密码: ");
        
        if (!newPassword.equals(confirmPassword)) {
            System.out.println("两次输入的密码不一致，无法修改密码！");
            return;
        }

        currentUser.setPassword(newPassword);
        dataManager.updateUser(currentUser);
        System.out.println("密码修改成功！");
    }

    private void resetFrontDeskPassword() {
        List<User> frontDeskUsers = dataManager.getAllUsers().stream()
                .filter(user -> user.getUserType() == UserType.FRONT_DESK)
                .collect(Collectors.toList());

        if (frontDeskUsers.isEmpty()) {
            System.out.println("没有前台用户可以重置密码！");
            return;
        }

        System.out.println("\n===== 前台用户列表 =====");
        CinemaUtil.printUsers(frontDeskUsers);

        String username = InputUtil.readNonEmptyString("请输入要重置密码的前台用户名: ");
        User userToReset = dataManager.getUserByUsername(username);
        
        if (userToReset == null) {
            System.out.println("未找到该用户！");
            return;
        }
        
        if (userToReset.getUserType() != UserType.FRONT_DESK) {
            System.out.println("只能重置前台用户的密码！");
            return;
        }

        userToReset.setPassword("123456");
        userToReset.setNeedResetPassword(true);
        dataManager.updateUser(userToReset);
        
        CinemaUtil.addLog("重置前台 " + username + " 的密码", currentUser.getUsername());
        System.out.println("用户 " + username + " 的密码已重置为: 123456");
    }

    private void showMovieMenu() {
        while (true) {
            System.out.println("\n===== 影片管理 =====");
            System.out.println("1. 列出所有影片");
            System.out.println("2. 添加影片");
            System.out.println("3. 修改影片");
            System.out.println("4. 删除影片");
            System.out.println("5. 查询影片");
            System.out.println("6. 返回上级菜单");
            System.out.print("请选择操作: ");

            int choice = InputUtil.readIntRange("", 1, 6);

            switch (choice) {
                case 1:
                    listAllMovies();
                    break;
                case 2:
                    addMovie();
                    break;
                case 3:
                    modifyMovie();
                    break;
                case 4:
                    deleteMovie();
                    break;
                case 5:
                    searchMovie();
                    break;
                case 6:
                    return;
            }
        }
    }

    private void listAllMovies() {
        System.out.println("\n===== 所有影片列表 =====");
        List<Movie> movies = dataManager.getAllMovies();
        
        if (movies.isEmpty()) {
            System.out.println("当前没有影片信息");
        } else {
            for (int i = 0; i < movies.size(); i++) {
                System.out.println("\n影片 " + (i + 1) + ":");
                System.out.println(movies.get(i));
                System.out.println("-------------------------------");
            }
        }
        
        InputUtil.pressEnterToContinue();
    }

    private void addMovie() {
        System.out.println("\n===== 添加影片 =====");
        String id = CinemaUtil.generateUniqueId();
        String title = InputUtil.readNonEmptyString("请输入片名: ");
        String director = InputUtil.readNonEmptyString("请输入导演: ");
        String actors = InputUtil.readNonEmptyString("请输入主演: ");
        String plot = InputUtil.readNonEmptyString("请输入剧情简介: ");
        int duration = InputUtil.readIntRange("请输入时长(分钟): ", 1, 500);
        double rating = InputUtil.readDoubleRange("请输入评分(0-10分): ", 0, 10);
        
        Movie movie = new Movie(id, title, director, actors, plot, duration, rating);
        dataManager.addMovie(movie);
        
        System.out.println("影片添加成功！");
    }

    private void modifyMovie() {
        System.out.println("\n===== 修改影片 =====");
        List<Movie> movies = dataManager.getAllMovies();
        
        if (movies.isEmpty()) {
            System.out.println("当前没有影片信息");
            return;
        }
        
        CinemaUtil.printMovies(movies);
        int index = InputUtil.readIntRange("请选择要修改的影片编号: ", 1, movies.size()) - 1;
        Movie movieToModify = movies.get(index);
        
        System.out.println("\n当前影片信息:");
        System.out.println(movieToModify);
        
        System.out.println("\n请输入新的影片信息(不修改请直接回车):");
        String title = InputUtil.readString("片名(" + movieToModify.getTitle() + "): ");
        String director = InputUtil.readString("导演(" + movieToModify.getDirector() + "): ");
        String actors = InputUtil.readString("主演(" + movieToModify.getActors() + "): ");
        String plot = InputUtil.readString("剧情简介: ");
        
        String durationStr = InputUtil.readString("时长(" + movieToModify.getDuration() + "分钟): ");
        String ratingStr = InputUtil.readString("评分(" + movieToModify.getRating() + "分): ");
        
        if (!title.isEmpty()) {
            movieToModify.setTitle(title);
        }
        
        if (!director.isEmpty()) {
            movieToModify.setDirector(director);
        }
        
        if (!actors.isEmpty()) {
            movieToModify.setActors(actors);
        }
        
        if (!plot.isEmpty()) {
            movieToModify.setPlot(plot);
        }
        
        if (!durationStr.isEmpty()) {
            try {
                int duration = Integer.parseInt(durationStr);
                if (duration > 0 && duration <= 500) {
                    movieToModify.setDuration(duration);
                } else {
                    System.out.println("时长必须在1-500分钟之间，此项未修改");
                }
            } catch (NumberFormatException e) {
                System.out.println("时长格式不正确，此项未修改");
            }
        }
        
        if (!ratingStr.isEmpty()) {
            try {
                double rating = Double.parseDouble(ratingStr);
                if (rating >= 0 && rating <= 10) {
                    movieToModify.setRating(rating);
                } else {
                    System.out.println("评分必须在0-10分之间，此项未修改");
                }
            } catch (NumberFormatException e) {
                System.out.println("评分格式不正确，此项未修改");
            }
        }
        
        dataManager.updateMovie(movieToModify);
        System.out.println("影片修改成功！");
    }

    private void deleteMovie() {
        System.out.println("\n===== 删除影片 =====");
        List<Movie> movies = dataManager.getAllMovies();
        
        if (movies.isEmpty()) {
            System.out.println("当前没有影片信息");
            return;
        }
        
        CinemaUtil.printMovies(movies);
        int index = InputUtil.readIntRange("请选择要删除的影片编号: ", 1, movies.size()) - 1;
        Movie movieToDelete = movies.get(index);
        
        boolean confirm = InputUtil.readBoolean("确定要删除影片《" + movieToDelete.getTitle() + "》吗？此操作不可恢复！");
        if (!confirm) {
            System.out.println("操作已取消！");
            return;
        }
        
        boolean success = dataManager.deleteMovie(movieToDelete.getId());
        if (success) {
            System.out.println("影片删除成功！");
        } else {
            System.out.println("删除失败：该影片有场次正在上映，不能删除！");
        }
    }

    private void searchMovie() {
        System.out.println("\n===== 查询影片 =====");
        System.out.println("(输入条件后按回车，不填则忽略该条件)");
        String title = InputUtil.readString("片名: ");
        String director = InputUtil.readString("导演: ");
        String actors = InputUtil.readString("主演: ");
        
        List<Movie> searchResults = dataManager.searchMovies(title, director, actors);
        
        System.out.println("\n===== 查询结果 =====");
        if (searchResults.isEmpty()) {
            System.out.println("未找到匹配的影片");
        } else {
            for (int i = 0; i < searchResults.size(); i++) {
                System.out.println("\n影片 " + (i + 1) + ":");
                System.out.println(searchResults.get(i));
                System.out.println("-------------------------------");
            }
        }
        
        InputUtil.pressEnterToContinue();
    }

    private void showScreeningMenu() {
        while (true) {
            System.out.println("\n===== 排片管理 =====");
            System.out.println("1. 列出所有场次");
            System.out.println("2. 增加场次");
            System.out.println("3. 修改场次");
            System.out.println("4. 删除场次");
            System.out.println("5. 自动排片");
            System.out.println("6. 返回上级菜单");
            System.out.print("请选择操作: ");

            int choice = InputUtil.readIntRange("", 1, 6);

            switch (choice) {
                case 1:
                    listAllScreenings();
                    break;
                case 2:
                    addScreening();
                    break;
                case 3:
                    modifyScreening();
                    break;
                case 4:
                    deleteScreening();
                    break;
                case 5:
                    autoScheduleScreenings();
                    break;
                case 6:
                    return;
            }
        }
    }

    private void listAllScreenings() {
        System.out.println("\n===== 场次列表 =====");
        System.out.println("1. 查看当日场次");
        System.out.println("2. 查看3日内场次");
        System.out.println("3. 查看一周内场次");
        
        int choice = InputUtil.readIntRange("请选择: ", 1, 3);
        
        List<Screening> screenings;
        switch (choice) {
            case 1:
                screenings = CinemaUtil.getTodayScreenings();
                System.out.println("\n===== 当日场次 =====");
                break;
            case 2:
                screenings = CinemaUtil.getThreeDayScreenings();
                System.out.println("\n===== 3日内场次 =====");
                break;
            case 3:
                screenings = CinemaUtil.getWeekScreenings();
                System.out.println("\n===== 一周内场次 =====");
                break;
            default:
                screenings = new ArrayList<>();
        }
        
        CinemaUtil.printScreenings(screenings);
        InputUtil.pressEnterToContinue();
    }

    private void addScreening() {
        System.out.println("\n===== 增加场次 =====");
        List<Movie> movies = dataManager.getAllMovies();
        
        if (movies.isEmpty()) {
            System.out.println("当前没有影片信息，请先添加影片！");
            return;
        }
        
        System.out.println("\n请选择电影:");
        CinemaUtil.printMovies(movies);
        int movieIndex = InputUtil.readIntRange("请输入电影编号: ", 1, movies.size()) - 1;
        Movie selectedMovie = movies.get(movieIndex);
        
        System.out.println("\n请选择放映厅:");
        List<Hall> halls = dataManager.getAllHalls();
        for (int i = 0; i < halls.size(); i++) {
            System.out.println((i + 1) + ". " + halls.get(i));
        }
        int hallIndex = InputUtil.readIntRange("请输入放映厅编号: ", 1, halls.size()) - 1;
        Hall selectedHall = halls.get(hallIndex);
        
        LocalDateTime startTime = InputUtil.readDateTime("请输入开始时间");
        
        // 检查是否可以安排该场次
        if (startTime.isBefore(LocalDateTime.now())) {
            System.out.println("不能安排过去的场次！");
            return;
        }
        
        // 检查时间冲突
        LocalDateTime endTime = startTime.plusMinutes(selectedMovie.getDuration());
        boolean hasConflict = dataManager.getAllScreenings().stream()
                .filter(s -> s.getHall().getId().equals(selectedHall.getId()))
                .anyMatch(s -> {
                    LocalDateTime existingStart = s.getStartTime();
                    LocalDateTime existingEnd = existingStart.plusMinutes(s.getMovie().getDuration());
                    return !(endTime.isBefore(existingStart) || startTime.isAfter(existingEnd));
                });
        
        if (hasConflict) {
            System.out.println("该时间段与其他场次冲突，无法安排！");
            return;
        }
        
        double price = InputUtil.readDoubleRange("请输入票价: ", 0.1, 1000);
        
        Screening newScreening = new Screening(
            CinemaUtil.generateUniqueId(),
            selectedMovie,
            selectedHall,
            startTime,
            price
        );
        
        dataManager.addScreening(newScreening);
        System.out.println("场次添加成功！");
    }

    private void modifyScreening() {
        System.out.println("\n===== 修改场次 =====");
        List<Screening> screenings = CinemaUtil.getWeekScreenings();
        
        if (screenings.isEmpty()) {
            System.out.println("没有可修改的场次");
            return;
        }
        
        CinemaUtil.printScreenings(screenings);
        int index = InputUtil.readIntRange("请选择要修改的场次编号: ", 1, screenings.size()) - 1;
        Screening screeningToModify = screenings.get(index);
        
        // 检查该场次是否有售票
        if (screeningToModify.getSoldSeats() > 0) {
            System.out.println("该场次已有票售出，无法修改！");
            return;
        }
        
        System.out.println("\n当前场次信息:");
        System.out.println(screeningToModify);
        
        System.out.println("\n请选择要修改的内容:");
        System.out.println("1. 电影");
        System.out.println("2. 时间");
        System.out.println("3. 票价");
        System.out.println("4. 取消修改");
        
        int choice = InputUtil.readIntRange("请选择: ", 1, 4);
        
        switch (choice) {
            case 1:
                List<Movie> movies = dataManager.getAllMovies();
                System.out.println("\n请选择新的电影:");
                CinemaUtil.printMovies(movies);
                int movieIndex = InputUtil.readIntRange("请输入电影编号: ", 1, movies.size()) - 1;
                Movie selectedMovie = movies.get(movieIndex);
                screeningToModify.setMovie(selectedMovie);
                break;
            case 2:
                LocalDateTime newStartTime = InputUtil.readDateTime("请输入新的开始时间");
                
                if (newStartTime.isBefore(LocalDateTime.now())) {
                    System.out.println("不能安排过去的场次！");
                    return;
                }
                
                // 检查时间冲突
                LocalDateTime newEndTime = newStartTime.plusMinutes(screeningToModify.getMovie().getDuration());
                boolean hasConflict = dataManager.getAllScreenings().stream()
                        .filter(s -> s.getHall().getId().equals(screeningToModify.getHall().getId()))
                        .filter(s -> !s.getId().equals(screeningToModify.getId())) // 排除自身
                        .anyMatch(s -> {
                            LocalDateTime existingStart = s.getStartTime();
                            LocalDateTime existingEnd = existingStart.plusMinutes(s.getMovie().getDuration());
                            return !(newEndTime.isBefore(existingStart) || newStartTime.isAfter(existingEnd));
                        });
                
                if (hasConflict) {
                    System.out.println("该时间段与其他场次冲突，无法安排！");
                    return;
                }
                
                screeningToModify.setStartTime(newStartTime);
                break;
            case 3:
                double newPrice = InputUtil.readDoubleRange("请输入新票价: ", 0.1, 1000);
                screeningToModify.setPrice(newPrice);
                break;
            case 4:
                return;
        }
        
        boolean success = dataManager.updateScreening(screeningToModify);
        if (success) {
            CinemaUtil.addLog("修改场次信息：场次时间" + 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(screeningToModify.getStartTime()) +
                "，片名" + screeningToModify.getMovie().getTitle(), 
                currentUser.getUsername());
            System.out.println("场次修改成功！");
        } else {
            System.out.println("修改失败，请重试！");
        }
    }

    private void deleteScreening() {
        System.out.println("\n===== 删除场次 =====");
        List<Screening> screenings = CinemaUtil.getWeekScreenings();
        
        if (screenings.isEmpty()) {
            System.out.println("没有可删除的场次");
            return;
        }
        
        CinemaUtil.printScreenings(screenings);
        int index = InputUtil.readIntRange("请选择要删除的场次编号: ", 1, screenings.size()) - 1;
        Screening screeningToDelete = screenings.get(index);
        
        boolean confirm = InputUtil.readBoolean("确定要删除该场次吗？此操作不可恢复！");
        if (!confirm) {
            System.out.println("操作已取消！");
            return;
        }
        
        boolean success = dataManager.deleteScreening(screeningToDelete.getId());
        if (success) {
            CinemaUtil.addLog("删除场次信息：场次时间" + 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(screeningToDelete.getStartTime()) +
                "，片名" + screeningToDelete.getMovie().getTitle(), 
                currentUser.getUsername());
            System.out.println("场次删除成功！");
        } else {
            System.out.println("删除失败：该场次已有票售出，不能删除！");
        }
    }

    private void autoScheduleScreenings() {
        System.out.println("\n===== 自动排片 =====");
        List<Movie> movies = dataManager.getAllMovies();
        
        if (movies.isEmpty()) {
            System.out.println("当前没有影片信息，请先添加影片！");
            return;
        }
        
        LocalDate startDate = InputUtil.readDate("请输入开始日期");
        int days = InputUtil.readIntRange("请输入排片天数(1-7): ", 1, 7);
        
        List<Hall> halls = dataManager.getAllHalls();
        List<Screening> newScreenings = CinemaUtil.autoScheduleScreenings(movies, halls, startDate, days);
        
        System.out.println("\n===== 自动排片结果 =====");
        System.out.println("已生成 " + newScreenings.size() + " 个场次");
        
        if (!newScreenings.isEmpty()) {
            boolean confirm = InputUtil.readBoolean("是否保存这些排片？");
            if (confirm) {
                for (Screening screening : newScreenings) {
                    dataManager.addScreening(screening);
                }
                System.out.println("自动排片已保存！");
            } else {
                System.out.println("操作已取消！");
            }
        }
    }

    private void showSalesMenu() {
        while (true) {
            System.out.println("\n===== 销售数据 =====");
            System.out.println("1. 查看当日销售数据");
            System.out.println("2. 查看当周销售数据");
            System.out.println("3. 查看当月销售数据");
            System.out.println("4. 返回上级菜单");
            System.out.print("请选择操作: ");

            int choice = InputUtil.readIntRange("", 1, 4);

            switch (choice) {
                case 1:
                    showDailySales();
                    break;
                case 2:
                    showWeeklySales();
                    break;
                case 3:
                    showMonthlySales();
                    break;
                case 4:
                    return;
            }
        }
    }

    private void showDailySales() {
        System.out.println("\n===== 当日销售数据 =====");
        LocalDate today = LocalDate.now();
        List<Ticket> dailyTickets = dataManager.getSaleStatistics().getTicketsByDate(today);
        
        // 按场次分组统计
        List<Screening> todayScreenings = CinemaUtil.getTodayScreenings();
        System.out.println("\n各场次销售情况:");
        System.out.println("----------------------------------------------------------");
        System.out.printf("%-30s %-10s %-8s %-8s %-8s\n", "场次", "票价", "售票数", "退票数", "销售额");
        System.out.println("----------------------------------------------------------");
        
        for (Screening screening : todayScreenings) {
            List<Ticket> screeningTickets = dailyTickets.stream()
                    .filter(t -> t.getScreening().getId().equals(screening.getId()))
                    .collect(Collectors.toList());
            
            int soldCount = (int) screeningTickets.stream()
                    .filter(t -> t.getStatus() == TicketStatus.VALID || t.getStatus() == TicketStatus.USED)
                    .count();
            
            int refundCount = (int) screeningTickets.stream()
                    .filter(t -> t.getStatus() == TicketStatus.REFUNDED)
                    .count();
            
            double sales = screeningTickets.stream()
                    .filter(t -> t.getStatus() == TicketStatus.VALID || t.getStatus() == TicketStatus.USED)
                    .mapToDouble(Ticket::getPrice)
                    .sum();
            
            String screeningInfo = screening.getMovie().getTitle() + " " + 
                    screening.getStartTime().format(DateTimeFormatter.ofPattern("HH:mm"));
            
            System.out.printf("%-30s %-10.2f %-8d %-8d %-8.2f\n", 
                    screeningInfo, screening.getPrice(), soldCount, refundCount, sales);
        }
        
        // 汇总数据
        int totalSoldCount = dataManager.getSaleStatistics().getValidTicketCount(dailyTickets);
        double totalSales = dataManager.getSaleStatistics().getValidTicketAmount(dailyTickets);
        int totalRefundCount = dataManager.getSaleStatistics().getRefundedTicketCount(dailyTickets);
        double totalRefundAmount = dataManager.getSaleStatistics().getRefundedTicketAmount(dailyTickets);
        
        System.out.println("----------------------------------------------------------");
        System.out.println("当日销售总计:");
        System.out.println("总销售票数: " + totalSoldCount + " 张");
        System.out.println("总销售金额: " + totalSales + " 元");
        System.out.println("总退票数: " + totalRefundCount + " 张");
        System.out.println("退票金额: " + totalRefundAmount + " 元");
        System.out.println("净销售额: " + (totalSales - totalRefundAmount) + " 元");
        
        InputUtil.pressEnterToContinue();
    }

    private void showWeeklySales() {
        System.out.println("\n===== 当周销售数据 =====");
        LocalDate today = LocalDate.now();
        LocalDate weekStart = today.minusDays(today.getDayOfWeek().getValue() - 1); // 本周一
        List<Ticket> weeklyTickets = dataManager.getSaleStatistics().getTicketsForWeek(weekStart);
        
        // 汇总数据
        int totalSoldCount = dataManager.getSaleStatistics().getValidTicketCount(weeklyTickets);
        double totalSales = dataManager.getSaleStatistics().getValidTicketAmount(weeklyTickets);
        int totalRefundCount = dataManager.getSaleStatistics().getRefundedTicketCount(weeklyTickets);
        double totalRefundAmount = dataManager.getSaleStatistics().getRefundedTicketAmount(weeklyTickets);
        
        System.out.println("本周销售总计 (" + weekStart + " 至 " + weekStart.plusDays(6) + "):");
        System.out.println("总销售票数: " + totalSoldCount + " 张");
        System.out.println("总销售金额: " + totalSales + " 元");
        System.out.println("总退票数: " + totalRefundCount + " 张");
        System.out.println("退票金额: " + totalRefundAmount + " 元");
        System.out.println("净销售额: " + (totalSales - totalRefundAmount) + " 元");
        
        InputUtil.pressEnterToContinue();
    }

    private void showMonthlySales() {
        System.out.println("\n===== 当月销售数据 =====");
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        int month = today.getMonthValue();
        
        List<Ticket> monthlyTickets = dataManager.getSaleStatistics().getTicketsForMonth(year, month);
        
        // 汇总数据
        int totalSoldCount = dataManager.getSaleStatistics().getValidTicketCount(monthlyTickets);
        double totalSales = dataManager.getSaleStatistics().getValidTicketAmount(monthlyTickets);
        int totalRefundCount = dataManager.getSaleStatistics().getRefundedTicketCount(monthlyTickets);
        double totalRefundAmount = dataManager.getSaleStatistics().getRefundedTicketAmount(monthlyTickets);
        
        System.out.println(year + "年" + month + "月销售总计:");
        System.out.println("总销售票数: " + totalSoldCount + " 张");
        System.out.println("总销售金额: " + totalSales + " 元");
        System.out.println("总退票数: " + totalRefundCount + " 张");
        System.out.println("退票金额: " + totalRefundAmount + " 元");
        System.out.println("净销售额: " + (totalSales - totalRefundAmount) + " 元");
        
        InputUtil.pressEnterToContinue();
    }
} 